package com.iflytek.jzcpx.procuracy.card.component;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import com.google.common.collect.Lists;
import com.iflytek.jzcpx.procuracy.card.common.ChineseNumToArabicNumUtil;
import com.iflytek.jzcpx.procuracy.card.common.enums.CardFieldEnum;
import com.iflytek.jzcpx.procuracy.card.common.enums.XYRFieldNameEnum;
import com.iflytek.jzcpx.procuracy.card.pojo.ElleResultData;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

/**
 * 字段格式转换
 *
 * @author <a href=mailto:ktyi@iflytek.com>伊开堂</a>
 * @date 2019/9/7 11:06
 */
public final class FieldConvertors {

	/** 中文数字 */
	private static final List<String> CHINESE_NUMBER = Lists.newArrayList("零", "一", "二", "三", "四", "五", "六", "七", "八",
			"九", "十");

	private static final List<String> CHINESE_NUMBER2 = Lists.newArrayList("零", "一", "两", "三", "四", "五", "六", "七", "八",
			"九", "十");

	private static final List<String> CHINESE_NUMBER3 = Lists.newArrayList("零", "一", "俩", "三", "四", "五", "六", "七", "八",
			"九", "十");

	/** 中文大写数字 */
	private static final List<String> CHINESE_MONEY_NUMBER = Lists.newArrayList("零", "壹", "贰", "叁", "肆", "伍", "陆", "柒",
			"捌", "玖", "拾");

	/** 中文金额单位 */
	private static final List<String> CHINESE_UNIT = Lists.newArrayList("十", "百", "千", "万", "亿");
	/** 匹配阿拉伯数字 */
	private static final Pattern ARABIC_NUMBER_PATTERN = Pattern.compile("\\d+(\\.\\d+)?");
	/** 中文数字 */
	private static final Pattern CHINESE_NUMBER_PATTERN = Pattern.compile("[〇零一二三四五六七八九十百千万亿]+");
	/** 卷宗册数 */
	private static final Pattern DOSSIER_VOLUMES_PATTERN = Pattern.compile("([零壹贰叁肆伍陆柒捌玖拾0-9]+)[卷册张]?");

	/**
	 * 处理 侦(调)查机关建议是否建议适用认罪认罚 、 检察机关是否适用认罪认罚 是否选项
	 *
	 * @param str 格式化
	 * @return 格式化失败返回""
	 */
	public static Function<String, String> whetherConvert() {
		return input -> {
			if (!StringUtils.isEmpty(input) && input.contains("认罪认罚")) {
				return "Y";
			}
			return "N";
		};
	}

	/**
	 * 处理 是否农村基层组织人员
	 *
	 * @param str 格式化
	 * @return 格式化失败返回""
	 */
	public static Function<String, String> sfncjczzryConvert() {
		return input -> {
			if (!StringUtils.isEmpty(input)) {
				return "Y";
			}
			return "N";
		};
	}

	/**
	 * 处理是否涉及恶势力犯罪 是否选项
	 *
	 * @param str 格式化
	 * @return 格式化失败返回""
	 */
	public static Function<String, String> whetherSfeslConvert() {
		return input -> {
			if (!StringUtils.isEmpty(input) && input.contains("恶势力犯罪")) {
				return "Y";
			}
			return "N";
		};
	}

	/**
	 * 处理共同犯罪性质
	 *
	 * @param str 格式化
	 * @return 格式化失败返回""
	 */
	public static Function<ElleResultData, String> gtfzxzConvert() {
		return elleResultData -> {
			List<ElleResultData.Suspect> suspects = elleResultData.getExtractInfoVec().get(0).getExtractInfo()
					.getSuspect();
			if (CollectionUtils.isEmpty(suspects) || suspects.size() == 1) {
				return "非共同犯罪";
			}
			return "一般共同犯罪";
		};
	}

	/**
	 * 处理嫌疑人的移送意见
	 *
	 * @param str 格式化
	 * @return 格式化失败返回""
	 */
	public static Function<ElleResultData, ElleResultData.Item> ysyjConvert() {
		return elleResultData -> {
			ElleResultData.Item ysyjItem = CardFieldEnum.AJ_YSYJ.getElleFieldExtractor().apply(elleResultData);
			if (null != ysyjItem) {
				return ysyjItem;
			}
			return null;
		};
	}

	/**
	 * 侦查机关是否建议适用认罪认罚
	 *
	 * @param str 格式化
	 * @return 格式化失败返回""
	 */
	public static Function<ElleResultData, ElleResultData.Item> zcjgsfjysyrzrfConvert() {
		return elleResultData -> {
			ElleResultData.Item zcjgsfjysyrzrfItem = CardFieldEnum.AJ_ZCJGSFJYSYRZRF.getElleFieldExtractor()
					.apply(elleResultData);
			if (null != zcjgsfjysyrzrfItem) {
				String mean = zcjgsfjysyrzrfItem.getMean();
				if (StringUtils.isNotBlank(mean) && mean.contains("认罪认罚")) {
					zcjgsfjysyrzrfItem.setMean("Y");
				} else {
					zcjgsfjysyrzrfItem.setMean("N");
				}
			} else {
				zcjgsfjysyrzrfItem = new ElleResultData.Item();
				zcjgsfjysyrzrfItem.setMean("N");
			}
			return zcjgsfjysyrzrfItem;
		};
	}

	/**
	 * 处理前科
	 *
	 * @param str 格式化
	 * @return 格式化失败返回""
	 */
	public static Function<ElleResultData.Label, String> qkConvert() {
		return label -> {
			String result = StringUtils.EMPTY;
			// 获取刑事处罚 劳教的值
			String criminalRecord = XYRFieldNameEnum.XSCF.getMc();// 刑事处罚
			String indoctrinationLabour = XYRFieldNameEnum.LJ.getMc();// 劳教
			ElleResultData.Item[] xscfItems = XYRFieldNameEnum.XSCF.getElleFieldExtractor().apply(label);
			ElleResultData.Item[] ljItems = XYRFieldNameEnum.LJ.getElleFieldExtractor().apply(label);
			if (ArrayUtils.isNotEmpty(xscfItems) && ArrayUtils.isNotEmpty(ljItems)) {
				result = criminalRecord;
			} else if (ArrayUtils.isNotEmpty(xscfItems) && ArrayUtils.isEmpty(ljItems)) {
				result = criminalRecord;
			} else if (ArrayUtils.isEmpty(xscfItems) && ArrayUtils.isNotEmpty(ljItems)) {
				result = indoctrinationLabour;
			} else {
				result = "无";
			}
			return result;
		};
	}

	/**
	 * 作案时年龄计算
	 *
	 * @param str 格式化
	 * @return 格式化失败返回""
	 */
	public static Function<ElleResultData.Label, String> zasnlConvert() {
		return label -> {
			String result = StringUtils.EMPTY;
			// 获取作案时间 生日
			String time = StringUtils.EMPTY;// 作案时间
			String birthday = StringUtils.EMPTY;// 生日
			ElleResultData.Item[] timeItems = XYRFieldNameEnum.ZASJ.getElleFieldExtractor().apply(label);
			if (ArrayUtils.isNotEmpty(timeItems)) {
				List<ElleResultData.Item> arr = Arrays.asList(timeItems);
				// 作案时间集合
				List<String> list = arr.stream().map(ElleResultData.Item::getMean)
						.filter(v -> StringUtils.isNotBlank(v)).collect(Collectors.toList());
				List<String> standList = new ArrayList<>();
				for (String xx : list) {
					String[] YMD = xx.split("-", -1);
					// 缺失年的直接过滤
					if (YMD.length < 1 || StringUtils.isEmpty(YMD[0])) {
						continue;
					}
					for (int i = 0; i < YMD.length; i++) {
						if (StringUtils.isEmpty(YMD[i])) {
							YMD[i] = "01";
						}
					}
					List<String> newList = Arrays.asList(YMD);
					xx = newList.stream().collect(Collectors.joining("-"));
					standList.add(xx);
				}
				// 时间正序排序
				DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
				standList.sort((String m1, String m2) -> {
					try {
						return sdf.parse(m1).compareTo(sdf.parse(m2));
					} catch (ParseException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					return 0;
				});
				// 取最早作案时间
				if (!CollectionUtils.isEmpty(standList)) {
					time = standList.get(0);
				}
			}
			ElleResultData.Item[] csrqItems = XYRFieldNameEnum.CSRQ.getElleFieldExtractor().apply(label);
			if (ArrayUtils.isNotEmpty(csrqItems)) {
				birthday = csrqItems[0].getMean();
			}
			if (StringUtils.isNotEmpty(birthday) && StringUtils.isNotEmpty(time)) {
				int age = getAge(birthday, time);
				result = String.valueOf(age);
				return result;
			}
			return result;
		};
	}
	
	
	public static BiFunction<ElleResultData.Label, ElleResultData, String> zasnlConvertNew() {
		return new BiFunction<ElleResultData.Label, ElleResultData, String>() {
			@Override
			public String apply(ElleResultData.Label label, ElleResultData elleResultData) {
				String result = StringUtils.EMPTY;
				// 获取作案时间 生日
				String time = StringUtils.EMPTY;// 作案时间
				String birthday = StringUtils.EMPTY;// 生日
				ElleResultData.Item caseTime = elleResultData.getExtractInfoVec().get(0).getExtractInfo().getCaseTime();// 案情摘要时间
				if (null != caseTime && StringUtils.isNotEmpty(caseTime.getMean())) {
					String caseTimeStr = caseTime.getMean();
					String[] YMD = caseTimeStr.split("-", -1);
					// 缺失年的直接过滤
					if (YMD.length > 1 && StringUtils.isNotEmpty(YMD[0])) {
						for (int i = 0; i < YMD.length; i++) {
							if (StringUtils.isEmpty(YMD[i])) {
								YMD[i] = "01";
							}
						}
						List<String> newList = Arrays.asList(YMD);
						caseTimeStr = newList.stream().collect(Collectors.joining("-"));
						time = caseTimeStr;
					}

				}
				if (StringUtils.isEmpty(time)) {
					ElleResultData.Item[] timeItems = XYRFieldNameEnum.ZASJ.getElleFieldExtractor().apply(label);
					if (ArrayUtils.isNotEmpty(timeItems)) {
						List<ElleResultData.Item> arr = Arrays.asList(timeItems);
						// 作案时间集合
						List<String> list = arr.stream().map(ElleResultData.Item::getMean)
								.filter(v -> StringUtils.isNotBlank(v)).collect(Collectors.toList());
						List<String> standList = new ArrayList<>();
						for (String xx : list) {
							String[] YMD = xx.split("-", -1);
							// 缺失年的直接过滤
							if (YMD.length < 1 || StringUtils.isEmpty(YMD[0])) {
								continue;
							}
							for (int i = 0; i < YMD.length; i++) {
								if (StringUtils.isEmpty(YMD[i])) {
									YMD[i] = "01";
								}
							}
							List<String> newList = Arrays.asList(YMD);
							xx = newList.stream().collect(Collectors.joining("-"));
							standList.add(xx);
						}
						// 时间正序排序
						DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
						standList.sort((String m1, String m2) -> {
							try {
								return sdf.parse(m1).compareTo(sdf.parse(m2));
							} catch (ParseException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
							return 0;
						});
						// 取最早作案时间
						if (!CollectionUtils.isEmpty(standList)) {
							time = standList.get(0);
						}
					}
				}

				ElleResultData.Item[] csrqItems = XYRFieldNameEnum.CSRQ.getElleFieldExtractor().apply(label);
				if (ArrayUtils.isNotEmpty(csrqItems)) {
					birthday = csrqItems[0].getMean();
				}
				if (StringUtils.isNotEmpty(birthday) && StringUtils.isNotEmpty(time)) {
					int age = getAge(birthday, time);
					result = String.valueOf(age);
					return result;
				}
				return result;

			}
		};
	}

	/*
	 * 计算时间之间相差得出年龄
	 */
	public static int getAge(String startTime, String endTime) {
		LocalDate beginDateTime = LocalDate.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
		LocalDate endDateTime = LocalDate.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
		int age = Period.between(beginDateTime, endDateTime).getYears();
		return age;
	}

	/**
	 * 处理是否为单位
	 *
	 * @param str 格式化
	 * @return 格式化失败返回""
	 */
	public static Function<ElleResultData.Label, String> sfwdwConvert() {
		return label -> {
			String result = "N";
			// 获取单位名称
			ElleResultData.Item[] dwmcItems = XYRFieldNameEnum.DWMC.getElleFieldExtractor().apply(label);
			if (ArrayUtils.isEmpty(dwmcItems)) {
				return result;
			}
			String dwmc = dwmcItems[0].getMean();
			if (StringUtils.isEmpty(dwmc)) {
				return result;
			}
			result = "Y";
			return result;
		};
	}

	/**
	 * 处理日期格式，
	 *
	 * @param format 最终格式化
	 * @return 格式化失败返回""
	 */
	public static Function<String, String> dateConvert(String format) {
		return input -> {
			if (StringUtils.isBlank(input)) {
				return "";
			}

			String result = input;
			// 格式化年
			String year = StringUtils.substringBefore(input, "年");
			int startIndexOfYear = StringUtils.indexOf(format, "y");
			int lastIndexOfYear = StringUtils.lastIndexOf(format, "y");
			if (!StringUtils.isNumeric(year)) {
				return "";
			}
			result = year + StringUtils.substring(format, lastIndexOfYear + 1);

			// 格式化月
			String month = StringUtils.substringBetween(input, "年", "月");
			int startIndexOfMonth = StringUtils.indexOf(result, "M");
			int lastIndexOfMonth = StringUtils.lastIndexOf(result, "M");
			int monthLength = lastIndexOfMonth - startIndexOfMonth + 1;
			if (monthLength > 2 || !StringUtils.isNumeric(month)) {
				return "";
			}
			if (monthLength > 0) {
				if (monthLength == 2) {
					month = StringUtils.leftPad(month, 2, "0");
				}
				result = StringUtils.substring(result, 0, startIndexOfMonth) + month
						+ StringUtils.substring(result, lastIndexOfMonth + 1, result.length());
			}

			// 格式化日
			String day = StringUtils.substringBetween(input, "月", "日");
			int startIndexOfDay = StringUtils.indexOf(result, "d");
			int lastIndexOfDay = StringUtils.lastIndexOf(result, "d");
			int dayLength = lastIndexOfDay - startIndexOfDay + 1;
			if (dayLength > 2 || !StringUtils.isNumeric(day)) {
				return "";
			}
			if (dayLength > 0) {
				if (dayLength == 2) {
					day = StringUtils.leftPad(day, 2, "0");
				}
				result = StringUtils.substring(result, 0, startIndexOfDay) + day
						+ StringUtils.substring(result, lastIndexOfDay + 1, result.length());
			}

			return result;
		};
	}

	/**
	 * 日期格式拼接，
	 *
	 * @param format 最终格式化
	 * @return 格式化失败返回""
	 */
	public static Function<String, String> dateContactConvert(String format) {
		return input -> {
			if (StringUtils.isBlank(input)) {
				return "";
			}

			String result = input;
			result = result + format;

			return result;
		};
	}

	/**
	 * 刑期后处理
	 * 
	 * @author dgyu
	 * @param address
	 * @return
	 */
	public static List<Map<String, String>> prisonTermOfFIResolution(String prisonTermOfFI) {
		String regex = "(?<year>[^年]+零|.*?年|.*?年)?(?<month>[^月]+月|.*?月|.*?月)?(?<day>[^天]+天|.*?天|.*?天)?(?<week>[^周]+周|.*?周|.*?周)?(?<week2>[^星期]+星期|.*?星期|.*?星期)?(?<week3>[^礼拜]+礼拜|.*?礼拜|.*?礼拜)?";
		Matcher m = Pattern.compile(regex).matcher(prisonTermOfFI);
		String year = null, month = null, day = null, week = null, week2 = null, week3 = null;
		List<Map<String, String>> table = new ArrayList<Map<String, String>>();
		Map<String, String> row = null;
		while (m.find()) {
			row = new LinkedHashMap<String, String>();

			year = m.group("year");
			row.put("year", year == null ? "" : year.trim());

			month = m.group("month");
			row.put("month", month == null ? "" : month.trim());

			day = m.group("day");
			row.put("day", day == null ? "" : day.trim());

			week = m.group("week");
			row.put("week", week == null ? "" : week.trim());

			week2 = m.group("week2");
			row.put("week2", week2 == null ? "" : week2.trim());

			week3 = m.group("week3");
			row.put("week3", week3 == null ? "" : week3.trim());

			table.add(row);
		}
		return table;
	}

	/**
	 * 判断一个字符串是否是数字。
	 * 
	 * @param string
	 * @return
	 */
	public static boolean isNumber(String string) {
		if (string == null)
			return false;
		Pattern pattern = Pattern.compile("^-?\\d+(\\.\\d+)?$");
		return pattern.matcher(string).matches();
	}

	/**
	 * 刑期转换成阿拉伯数字 格式为X年X月X日
	 * 
	 * @return
	 */
	public static Function<String, String> prisonTermOfFIAfterConvert() {
		return input -> {
			if (StringUtils.isBlank(input)) {
				return "";
			}
			String result = input;
			List<Map<String, String>> listMap = prisonTermOfFIResolution(result);
			if (!CollectionUtils.isEmpty(listMap)) {
				Map<String, String> map = listMap.get(0);
				// 年
				String year = map.get("year");
				// 月
				String month = map.get("month");
				// 天
				String day = map.get("day");
				// 周
				String week = map.get("week");
				// 周
				String week2 = map.get("week2");
				// 周
				String week3 = map.get("week3");
				// 阿拉伯数字 年 月 天 周
				int arabYear = 0, arabMonth = 0, arabDay = 0;
				String formatStr = "%d年%d月%d天";
				if (StringUtils.isNotEmpty(year)) {
					year = year.substring(0, year.length() - 1);
					boolean isNumber = isNumber(year);
					if (isNumber) {
						arabYear = Integer.parseInt(year);
					} else {
						arabYear=ChineseNumToArabicNumUtil.chineseNumToArabicNum(year);
					}
				}

				if (StringUtils.isNotEmpty(month)) {
					month = month.substring(0, month.length() - 1);
					boolean isNumber = isNumber(month);
					if (isNumber) {
						arabMonth = Integer.parseInt(month);
					} else {
						if (month.indexOf("个") > -1 || month.indexOf("個") > -1) {
							month = month.substring(0, month.length() - 1);
							isNumber = isNumber(month);
							if (isNumber) {
								arabMonth = Integer.parseInt(month);
							} else {
								arabMonth=ChineseNumToArabicNumUtil.chineseNumToArabicNum(month);
							}
						}
					}
				}

				if (StringUtils.isNotEmpty(day)) {
					day = day.substring(0, day.length() - 1);
					boolean isNumber = isNumber(day);
					if (isNumber) {
						arabDay = Integer.parseInt(day);
					} else {
						arabDay=ChineseNumToArabicNumUtil.chineseNumToArabicNum(day);
					}
				}

				if (StringUtils.isNotEmpty(week)) {
					week = week.substring(0, week.length() - 1);
					boolean isNumber = isNumber(week);
					if (isNumber) {
						arabDay = Integer.parseInt(week) * 7;
					} else {
						arabDay=ChineseNumToArabicNumUtil.chineseNumToArabicNum(week)*7;
					}
				}

				if (StringUtils.isNotEmpty(week2)) {
					week2 = week2.substring(0, week2.length() - 2);
					boolean isNumber = isNumber(week2);
					if (isNumber) {
						arabDay = Integer.parseInt(week2) * 7;
					} else {
						if (week2.indexOf("个") > -1 || week2.indexOf("個") > -1) {
							week2 = week2.substring(0, week2.length() - 1);
							isNumber = isNumber(week2);
							if (isNumber) {
								arabDay = Integer.parseInt(week2) * 7;
							} else {
								arabDay=ChineseNumToArabicNumUtil.chineseNumToArabicNum(week2)*7;
							}
						}
					}
				}

				if (StringUtils.isNotEmpty(week3)) {
					week3 = week3.substring(0, week3.length() - 2);
					boolean isNumber = isNumber(week3);
					if (isNumber) {
						arabDay = Integer.parseInt(week3) * 7;
					} else {
						if (week3.indexOf("个") > -1 || week3.indexOf("個") > -1) {
							week3 = week3.substring(0, week3.length() - 1);
							isNumber = isNumber(week3);
							if (isNumber) {
								arabDay = Integer.parseInt(week2) * 7;
							} else {
								arabDay=ChineseNumToArabicNumUtil.chineseNumToArabicNum(week3)*7;
							}
						}
					}
				}
				return arabYear > -1 && arabMonth > -1 && arabDay > -1
						? String.format(formatStr, arabYear, arabMonth, arabDay)
						: result;

			}
			return result;
		};
	}

	public static void main(String[] args) {

		System.out.println(prisonTermOfFIAfterConvert().apply("一个月"));
		System.out.println(prisonTermOfFIAfterConvert().apply("一周"));

		System.out.println(prisonTermOfFIAfterConvert().apply("二个礼拜"));
		System.out.println(prisonTermOfFIAfterConvert().apply("三个礼拜"));
		System.out.println(prisonTermOfFIAfterConvert().apply("四个星期"));

		System.out.println(prisonTermOfFIAfterConvert().apply("三年5个月"));
		System.out.println(prisonTermOfFIAfterConvert().apply("十五年"));
		System.out.println("********************");
		System.out.println(dateConvert("yyyy-MM-dd").apply("2019年8月1日"));
		System.out.println(dateConvert("yyyy-MM-dd").apply("2019年08月1日"));
		System.out.println(dateConvert("yyyy-MM-dd").apply("2019年8月10日"));
		System.out.println(dateConvert("yyyy-MM-dd").apply("2019年08月10日"));

		System.out.println(moneyConvert(16, 4).apply("人民币0.05元"));
		System.out.println(moneyConvert(16, 4).apply("人民币0.5元"));
		System.out.println(moneyConvert(16, 4).apply("人民币0.50元"));
		System.out.println(moneyConvert(16, 4).apply("人民币50元"));
		System.out.println(moneyConvert(16, 4).apply("人民币500.45元"));
		System.out.println(moneyConvert(16, 4).apply("人民币5000元"));
		System.out.println(moneyConvert(16, 4).apply("人民币5万元"));
		System.out.println(moneyConvert(16, 4).apply("人民币50.45万元"));
		System.out.println(moneyConvert(16, 4).apply("人民币50.45321万元"));
		System.out.println(moneyConvert(16, 4).apply("人民币5亿元"));
		System.out.println(moneyConvert(16, 4).apply("人民币5.4587亿元"));

		System.out.println("--------------");
		System.out.println(moneyConvert(16, 4).apply("人民币一元"));
		System.out.println(moneyConvert(16, 4).apply("人民币二十一元"));
		System.out.println(moneyConvert(16, 4).apply("人民币三百元"));
		System.out.println(moneyConvert(16, 4).apply("人民币三百二十元"));
		System.out.println(moneyConvert(16, 4).apply("人民币三百二十一元"));
		System.out.println(moneyConvert(16, 4).apply("人民币三百零一元"));
		System.out.println(moneyConvert(16, 4).apply("人民币四千元"));
		System.out.println(moneyConvert(16, 4).apply("人民币四千零一元"));
		System.out.println(moneyConvert(16, 4).apply("人民币四千零二十一元"));
		System.out.println(moneyConvert(16, 4).apply("人民币四千三百元"));
		System.out.println(moneyConvert(16, 4).apply("人民币四千三百二十元"));
		System.out.println(moneyConvert(16, 4).apply("人民币四千三百二十一元"));
		System.out.println(moneyConvert(16, 4).apply("人民币四千三百零一元"));
		System.out.println(moneyConvert(16, 4).apply("人民币五万元"));
		System.out.println(moneyConvert(16, 4).apply("人民币五万四千元"));
		System.out.println(moneyConvert(16, 4).apply("人民币五万四千零一元"));
		System.out.println(moneyConvert(16, 4).apply("人民币五万四千零二十一元"));
		System.out.println(moneyConvert(16, 4).apply("人民币五万四千三百元"));
		System.out.println(moneyConvert(16, 4).apply("人民币五万四千三百二十元"));
		System.out.println(moneyConvert(16, 4).apply("人民币五万四千三百二十一元"));
		System.out.println(moneyConvert(16, 4).apply("人民币五万四千三百零一元"));
		System.out.println(moneyConvert(16, 4).apply("人民币六十五万元"));
		System.out.println(moneyConvert(16, 4).apply("人民币六十五万四千元"));
		System.out.println(moneyConvert(16, 4).apply("人民币六十五万四千零一元"));
		System.out.println(moneyConvert(16, 4).apply("人民币六十五万四千零二十一元"));
		System.out.println(moneyConvert(16, 4).apply("人民币六十五万四千三百元"));
		System.out.println(moneyConvert(16, 4).apply("人民币六十五万四千三百二十元"));
		System.out.println(moneyConvert(16, 4).apply("人民币六十五万四千三百二十一元"));
		System.out.println(moneyConvert(16, 4).apply("人民币六十五万四千三百零一元"));

		System.out.println(moneyConvert(16, 4).apply("人民币九亿八千七百六十五万四千三百二十一元"));

		System.out.println("==============");
		System.out.println(parseChineseNumber("五"));
		System.out.println(parseChineseNumber("五十"));
		System.out.println(parseChineseNumber("五十五"));
		System.out.println(parseChineseNumber("五百"));
		System.out.println(parseChineseNumber("五百零五"));
		System.out.println(parseChineseNumber("五百五十五"));
		System.out.println(parseChineseNumber("五千"));
		System.out.println(parseChineseNumber("五千五百"));
		System.out.println(parseChineseNumber("五千五百五十"));
		System.out.println(parseChineseNumber("五千五百五十五"));
		System.out.println(parseChineseNumber("五千五百零五"));
		System.out.println(parseChineseNumber("五千零五十五"));
		System.out.println(parseChineseNumber("五千零五"));

		String s1 = "2017-08-01 22:18:22";
		String s2 = "2018-08-01 22:17:22";
		String s3 = "2017-08-04 22:19:22";
		List<String> arr = new ArrayList<>();
		arr.add(s1);
		arr.add(s2);
		arr.add(s3);
		DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		// 时间正序排序
		arr.sort((String m1, String m2) -> {
			try {
				return sdf.parse(m1).compareTo(sdf.parse(m2));
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return 0;
		});
		System.out.println("按消息发送时间正序排序：");
		for (String message : arr) {
			System.out.println(message);
		}
		System.out.println("--------------");
		for (String message : arr.subList(1, arr.size())) {
			System.out.println(message);
		}
	}

	/**
	 * 返回原始字符串，或空字符串
	 *
	 * @return ""：如果字符串为null
	 */
	public static Function<String, String> defaultString() {
		return input -> {
			if (StringUtils.isBlank(input)) {
				return "";
			}
			return RegExUtils.removeAll(input, "[：，。；、,.:  ]");
		};
	}

	/** elle引擎4028版本在抽取身份证号时，结尾会多个点，因此需要特殊处理，引擎升级后可删除该方法 */
	public static Function<String, String> trimCertificate() {
		return input -> StringUtils.substring(StringUtils.defaultString(RegExUtils.removeAll(input, "[^0-9a-zA-Z]")), 0,
				18);
	}

	/**
	 * 金额格式化, 单位: 万元
	 *
	 * @param precision 有效位数, 小数点左边的位数
	 * @param scale     精度, 小数点右边的位数
	 *
	 * @return 十五万元 -> 15; 人民币5000元 -> 0.5
	 */
	public static Function<String, String> moneyConvert(int precision, int scale) {
		return input -> {
			if (StringUtils.isBlank(input)) {
				return input;
			}

			BigDecimal numberDecimal = new BigDecimal(0);
			// 中文单位 * 10000
			BigDecimal chineseMultiply = new BigDecimal(Math.pow(10, 4));

			// 处理亿之前的数字
			int yiIndex = StringUtils.indexOf(input, "亿");
			if (yiIndex != -1) {
				String numStr = StringUtils.substring(input, 0, yiIndex);
				numberDecimal = numberDecimal.add(parseNumber(numStr).multiply(chineseMultiply));

				input = StringUtils.substring(input, yiIndex + 1);
			}

			// 处理万之前的数字
			int wanIndex = StringUtils.indexOf(input, "万");
			if (wanIndex != -1) {
				String numStr = StringUtils.substring(input, 0, wanIndex);
				numberDecimal = numberDecimal.add(parseNumber(numStr));

				input = StringUtils.substring(input, wanIndex + 1);
			}

			// 处理万之后的数字
			if (StringUtils.isNotBlank(input)) {
				numberDecimal = numberDecimal.add(parseNumber(input).divide(chineseMultiply));
			}

			// 精度部分如果长度超过限制则返回 null
			return numberDecimal == null || numberDecimal.scale() > scale ? null : numberDecimal.toString();
		};
	}

	/** 处理字符串中的字符串, 如: 人民币 5000 元, */
	private static BigDecimal parseNumber(String number) {
		Matcher chineseNumMatcher = CHINESE_NUMBER_PATTERN.matcher(number);
		if (chineseNumMatcher.find()) {
			number = chineseNumMatcher.group();

			// 按中文数字处理
			return parseChineseNumber(number);
		} else {
			// 按阿拉伯数字处理
			Matcher arabicNumMatcher = ARABIC_NUMBER_PATTERN.matcher(number);
			if (!arabicNumMatcher.find()) {
				return new BigDecimal(0);
			}

			String numberStr = arabicNumMatcher.group();
			return new BigDecimal(numberStr);
		}
	}

	/** 处理万以下中文数字, 例: 二十四, 三百八, 四百五十六, 一千, 三千零八十七... */
	private static BigDecimal parseChineseNumber(String chinseNumber) {
		BigDecimal result = new BigDecimal(0);
		if (StringUtils.isBlank(chinseNumber)) {
			return result;
		}

		chinseNumber = StringUtils.remove(chinseNumber, "零");

		result = result.add(parseSingleChineseNumber(chinseNumber, "千"));
		chinseNumber = chinseNumber.contains("千") ? StringUtils.substringAfter(chinseNumber, "千") : chinseNumber;

		result = result.add(parseSingleChineseNumber(chinseNumber, "百"));
		chinseNumber = chinseNumber.contains("百") ? StringUtils.substringAfter(chinseNumber, "百") : chinseNumber;

		result = result.add(parseSingleChineseNumber(chinseNumber, "十"));
		chinseNumber = chinseNumber.contains("十") ? StringUtils.substringAfter(chinseNumber, "十") : chinseNumber;

		BigDecimal augend = parseSingleChineseNumber(chinseNumber, "");
		result = result.add(augend);

		return result;
	}

	/** 处理单个汉字数字, 超过则返回 0 */
	private static BigDecimal parseSingleChineseNumber(String chineseNumber, String chineseUnit) {
		if (StringUtils.isBlank(chineseUnit) && StringUtils.length(chineseNumber) == 1) {
			int index = CHINESE_NUMBER.indexOf(chineseNumber);
			int index2 = CHINESE_NUMBER2.indexOf(chineseNumber);
			int index3 = CHINESE_NUMBER3.indexOf(chineseNumber);
			List<Integer> listIndex = Arrays.asList(index, index2, index3);
			for (Integer i : listIndex) {
				if (i > 0) {
					return new BigDecimal(i);
				}
			}
			return new BigDecimal(CHINESE_NUMBER.indexOf(chineseNumber));
		}

		BigDecimal result = new BigDecimal(0);
		int times = CHINESE_UNIT.indexOf(chineseUnit) + 1;
		int unitIndex = StringUtils.indexOf(chineseNumber, chineseUnit);
		if (unitIndex != -1) {
			String numberStr = StringUtils.substring(chineseNumber, 0, unitIndex);
			if (StringUtils.length(numberStr) != 1) {
				return result;
			}

			int count = CHINESE_NUMBER.indexOf(numberStr);
			if (count > 9) {
				return result;
			}
			double pow = Math.pow(10, times);
			return new BigDecimal(count * pow);
		}
		return result;
	}

	/** 卷宗册数/光盘张数 */
	public static Function<String, String> columnConvert() {
		return input -> {
			if (StringUtils.isBlank(input)) {
				return null;
			}

			Matcher matcher = DOSSIER_VOLUMES_PATTERN.matcher(input);

			String numStr = null;
			while (matcher.find()) {
				String group = matcher.group(0);

				numStr = StringUtils.trimToEmpty(matcher.group(1));
				if (group.endsWith("册")) {
					break;
				}
			}

			if (StringUtils.isNumeric(numStr)) {
				return numStr;
			} else if (StringUtils.isBlank(numStr) || numStr.length() > 1 || !CHINESE_MONEY_NUMBER.contains(numStr)) {
				return null;
			} else {
				return String.valueOf(CHINESE_MONEY_NUMBER.indexOf(numStr));
			}
		};
	}
}
